package br.com.jdobjs.core;

import java.util.Collection;

import org.drools.runtime.StatefulKnowledgeSession;
import org.jboss.aop.joinpoint.MethodInvocation;

public abstract class AbstractRuleSecurityInterceptor {

	private RuleSecurityConfig config;

	public AbstractRuleSecurityInterceptor() {
		super();
		loadConfig();
	}

	protected void loadConfig() {
		setConfig(new DefaultRuleSecurityConfig());
	}

	public void setConfig(RuleSecurityConfig config) {
		this.config = config;
	}

	public abstract Object invoke(MethodInvocation invocation) throws Throwable;

	@SuppressWarnings("unchecked")
	protected boolean verifyAccess(MethodInvocation invocation, Object result,
			InvocationStep step) {
		final TargetInvocation targetInvocation = new TargetInvocation(
				buildFunctionName(invocation), invocation.getTargetObject(),
				step);

		final RuleSecurityConstraint constraint = new RuleSecurityConstraint();

		StatefulKnowledgeSession ksession = config.getKnowledgeBase()
				.newStatefulKnowledgeSession();

		ksession.insert(constraint);
		ksession.insert(targetInvocation);
		ksession.insert(targetInvocation.getTargetObject());
		ksession.insert(config.getUserCredentialsResolver()
				.getUserCredentials());

		if (result != null) {
			if (Collection.class.isInstance(result)) {
				for (Object resultItem : (Collection) result) {
					ksession.insert(resultItem);
				}
			} else {
				ksession.insert(result);
			}
		}

		ksession.fireAllRules();
		ksession.dispose();

		return constraint.isAccessGranted();
	}

	protected String buildFunctionName(MethodInvocation invocation) {
		final StringBuilder functionBuilder = new StringBuilder();
		functionBuilder.append(invocation.getTargetObject().getClass()
				.getSimpleName());
		functionBuilder.append(".");
		functionBuilder.append(invocation.getActualMethod().getName());
		final String function = functionBuilder.toString();
		return function;
	}
}
